package com.myk.game.gobangchess.rooms;

import com.myk.game.gobangchess.*;
import com.myk.game.gobangchess.constants.BoardStyleData;
import com.myk.game.gobangchess.constants.WinMode;
import com.myk.game.gobangchess.signs.GroundSign;
import com.myk.game.gobangchess.signs.LineSign;
import com.myk.game.gobangchess.Sign;
import com.myk.game.gobangchess.signs.TextSign;
import com.myk.game.gobangchess.signs.TitleSign;
import com.myk.game.gobangchess.utils.GridsUtils;

import java.util.ArrayList;
import java.util.Arrays;
import java.util.List;

/**
 * Squadro航队阵
 */
public class SquadroRoom extends Room {
    private static final String[] ColorArrows = new String[]{"", "#AA000000", "#AAFFFFFF"};
    private static final String[] ColorTexts = new String[]{"", "#FFDDDDDD", "#FF222222"};
    private static final String WinColor = "#FFDDAA22";
    private static final String ColorMove = "#BB2222DD";
    private static final String ColorHit = "#BBDD2222";
    private int rowStart, rowEnd, colStart, colEnd;

    private final Rule rule = new Rule0();

    private interface Rule {
        void reset();

        void doRule(int row, int col, int value);
    }

    private class Rule0 implements Rule {
        @Override
        public void reset() {
            originGrids = GridsUtils.createEmptyGrids(7, 7);
            curGrids = GridsUtils.copyGrids(originGrids);
            signList.clear();
            rowStart = 0;
            rowEnd = curGrids.length - 1;
            colStart = 0;
            colEnd = curGrids[0].length - 1;
            chessList = new ArrayList<>();
            List<Integer> chessSteps = Arrays.asList(3, 1, 2, 1, 3);
            for (int i = 0; i < chessSteps.size(); i++) {
                chessList.add(new Chess(1, new int[]{i + 1, 0}, chessSteps.get(i), Direction.RIGHT));
            }
            chessSteps = Arrays.asList(1, 3, 2, 3, 1);
            for (int i = 0; i < chessSteps.size(); i++) {
                chessList.add(new Chess(2, new int[]{0, i + 1}, chessSteps.get(i), Direction.DOWN));
            }
            updateBoard(new ArrayList<>());
        }

        @Override
        public void doRule(int row, int col, int value) {

            if (curGrids[row][col] != value) {
                return; //只能移动自己的棋子
            }
            Chess chess = getChess(row, col);
            if (chess == null || chess.win) {
                return;
            }
            clearBottoms();
            stepAdd();;
            List<Sign> tmpSignList = new ArrayList<>();
            for (int i = 0; i < chess.step; i++) {
                int move = 1;
                Chess opChess;
                do {
                    int[] pendingPosition = chess.getPendingPosition(move);
                    opChess = getChess(pendingPosition[0], pendingPosition[1]);
                    if (opChess != null) {
                        opChess.backToStart();
                        tmpSignList.add(new LineSign(getIndex(pendingPosition[0], pendingPosition[1]), getIndex(opChess.row, opChess.col), ColorHit, 1));
                        move++;
                    }
                } while (opChess != null);

                chess.move(move);
                if (move > 1) {
                    break;
                }
            }
            if (chess.row <= rowStart) {
                chess.win = true;
                chess.row = rowStart;
            }
            else if (chess.col <= colStart) {
                chess.win = true;
                chess.col = colStart;
            }
            else if (chess.row >= rowEnd) {
                chess.reverse(new int[]{rowEnd, chess.col});
                chess.row = rowEnd;
            }
            else if (chess.col >= colEnd) {
                chess.reverse(new int[]{chess.row, colEnd});
                chess.col = colEnd;
            }

            tmpSignList.add(new LineSign(getIndex(row, col), getIndex(chess.row, chess.col), ColorMove, 1));
            updateBoard(tmpSignList);

            if (checkWin()) {
                if (value == 1) {
                    doOver(WinMode.BLACK_WIN,player_black.getNickNameOrTemp() + "的黑方成功战胜" + player_white.getNickNameOrTemp() + "的白方");
                }
                else if (value == 2) {
                    doOver(WinMode.WHITE_WIN,player_white.getNickNameOrTemp() + "的白方成功战胜" + player_black.getNickNameOrTemp() + "的黑方");
                }
            }
            else {
                if (value == 1) {
                    noticeWhiteMove();
                }
                else if (value == 2) {
                    noticeBlackMove();
                }
            }
        }

        private boolean checkWin() {
            int win1 = 0, win2 = 0;
            for (Chess chess : chessList) {
                if (chess.win) {
                    if (chess.value == 1) {
                        win1++;
                    }
                    else if (chess.value == 2) {
                        win2++;
                    }
                }
            }
            return win1 >= 4 || win2 >= 4;
        }
    }

    enum Direction {
        UP, DOWN, LEFT, RIGHT
    }

    private List<Chess> chessList;

    public SquadroRoom(String roomName) {
        super(roomName, "\t\t\t\t来自法国Gigamic的抽象棋Squadro，双方棋子交错往返行进，利用冲撞击退对方棋子，4个棋子成功往返即可获胜。","航队阵",BoardStyleData.getGoBangStyle(7,7), true, true);
        rule.reset();
    }

    @Override
    public String getRuleText() {
        return "黑白双方轮流走棋，\n" +
                "每回合可选择一枚棋子沿航线移动N格\n" +
                "移动过程中若触碰敌方棋子，\n" +
                "将其击退并将越过被击退棋子；\n" +
                "棋子到达对岸后，将改变自身N值：\n" +
                "新的N值为（4-原N值）\n" +
                "获胜条件：任意4枚己方棋子往返航线1次";
    }

    @Override
    public String getCoordMode() {
        return "00000000";
    }

    @Override
    public void doStart() {
        overFlag = 1;//重置结束状态：对弈进行中未结束
        playingStartTime = System.currentTimeMillis(); //重置对弈开始时间
        rule.reset();
       /* if (player_black != null) {
            player_black.registerCustomBottom(cb_changeMode);
        }
        if (player_white != null) {
            player_white.registerCustomBottom(cb_changeMode);
        }*/
        DataManager.noticeAllGameStart(player_black, player_white, roomName);
        noticeBlackMove();
        preHistory();
    }

    @Override
    public void resetGrids() {
        step = 0;
        gameTip = "-1";
        rule.reset();
    }

    @Override
    public void doRule(int row, int col, int value) {
        rule.doRule(row, col, value);
    }

    private void updateBoard(List<Sign> tmpSignList) {
        curGrids = GridsUtils.copyGrids(originGrids);
        signList.clear(); //清除旧记号
        signList.add(new GroundSign(getIndex(0, 0), getIndex(curGrids.length - 1, curGrids[0].length - 1), "#FF66AADD", "#FF3388FF", 1.8f, 0, 0));
        for (Chess chess : chessList) {
            addSign(chess);
        }
        if (player_black==null&&player_white==null){
            signList.add(new TitleSign(0.5f,0.45f,0,"SQUADRO","#FF333333",1.1f));
        }
        signList.addAll(tmpSignList);
    }

    private void clearBottoms() {
        if (player_black != null) {
            if (player_black.findCustomBottomByTitle(this, "切换模式") != null) {
                player_black.clearCustomBottom();
                player_black.dispatchCustomBottom();
            }
        }
        if (player_white != null) {
            if (player_white.findCustomBottomByTitle(this, "切换模式") != null) {
                player_white.clearCustomBottom();
                player_white.dispatchCustomBottom();
            }
        }
    }

    public void addSign(Chess chess) {
        curGrids[chess.row][chess.col] = chess.value;
        if (chess.direction == Direction.DOWN) {
            signList.add(new LineSign(getIndex(rowStart, chess.col), getIndex(rowEnd, chess.col), ColorArrows[chess.value], 1));
        }
        else if (chess.direction == Direction.UP) {
            signList.add(new LineSign(getIndex(rowEnd, chess.col), getIndex(rowStart, chess.col), ColorArrows[chess.value], 1));
        }
        else if (chess.direction == Direction.RIGHT) {
            signList.add(new LineSign(getIndex(chess.row, colStart), getIndex(chess.row, colEnd), ColorArrows[chess.value], 1));
        }
        else if (chess.direction == Direction.LEFT) {
            signList.add(new LineSign(getIndex(chess.row, colEnd), getIndex(chess.row, colStart), ColorArrows[chess.value], 1));
        }
        int index = getIndex(chess.row, chess.col);
        String value = chess.getText();
        String color = value.equals("W") ? WinColor : ColorTexts[chess.value];
        signList.add(new TextSign(index, value, color));
    }

    private Chess getChess(int row, int col) {
        for (Chess chess : chessList) {
            if (chess.row == row && chess.col == col) {
                return chess;
            }
        }
        return null;
    }

    private static class Chess {
        public int value, row, col, step;
        public boolean win = false;
        public int[] start;
        public Direction direction;

        public Chess(int value, int[] start, int step, Direction direction) {
            this.value = value;
            this.row = start[0];
            this.col = start[1];
            this.start = start;
            this.step = step;
            this.direction = direction;
        }

        public void reverse(int[] start) {
            if (direction == Direction.DOWN) {
                direction = Direction.UP;
            }
            else if (direction == Direction.RIGHT) {
                direction = Direction.LEFT;
            }
            this.start = start;
            step = 4 - step;
        }

        public String getText() {
            if (win) {
                return "W";
            }
            return String.valueOf(step);
        }

        public void move(int move) {
            int[] pendingPosition = getPendingPosition(move);
            row = pendingPosition[0];
            col = pendingPosition[1];
        }

        public int[] getPendingPosition(int move) {
            if (direction == Direction.DOWN) {
                return new int[]{row + move, col};
            }
            else if (direction == Direction.UP) {
                return new int[]{row - move, col};
            }
            else if (direction == Direction.RIGHT) {
                return new int[]{row, col + move};
            }
            else if (direction == Direction.LEFT) {
                return new int[]{row, col - move};
            }
            return new int[]{0, 0};
        }

        public void backToStart() {
            row = start[0];
            col = start[1];
        }
    }

}